package com.xl.qa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.SPage;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.utils.JacksonUtils;
import com.xl.dao.domain.XlQuestion;
import com.xl.dao.domain.XlQuestionAnswer;
import com.xl.dao.domain.XlQuestionOrder;
import com.xl.dao.mapper.XlQuestionOrderMapper;
import com.xl.qa.enmus.QuestionOrderStateEnums;
import com.xl.qa.entity.param.*;
import com.xl.qa.entity.result.AddOrUpdQuesAnswerResult;
import com.xl.qa.entity.result.QuesOrderDetailsResult;
import com.xl.qa.entity.result.QuestionDetailsResult;
import com.xl.qa.service.QuestionAnswerService;
import com.xl.qa.service.QuestionOrderService;
import com.xl.qa.service.QuestionService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * @author 钟勇
 * Create in 2024/1/16 15:29
 */
@Service
@RequiredArgsConstructor
public class QuestionOrderServiceImpl implements QuestionOrderService {

    private final XlQuestionOrderMapper orderMapper;
    private final QuestionAnswerService answerService;
    private final QuestionService questionService;

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public Result<String> addQuesOrder(@NonNull AddQuesOrderParam param, UserInfo operator) {
        String operatorUserId = operator != null ? operator.getUserId() : null;
        Result<QuestionDetailsResult> questionDetailsRes = questionService.getQuestionDetails(param.getQuestionId());
        if (questionDetailsRes.isErr()) {
            return questionDetailsRes.create();
        }

        QuestionDetailsResult ques = questionDetailsRes.getResult();
        if (ques.getDisableFlag() != null && ques.getDisableFlag().equals(1)) {
            return ResultEnums.BusinessError.getResult("问卷已停用，无法提交");
        }

        //0元单默认支付
        QuestionOrderStateEnums orderStateEnums = QuestionOrderStateEnums.add;
        if (ques.getPrice() == null || ques.getPrice().equals(0)) {
            orderStateEnums = QuestionOrderStateEnums.paid;
        }

        XlQuestionOrder data = new XlQuestionOrder()
                .setQuestionId(param.getQuestionId())
                .setQuestionTitle(ques.getQuestionTitle())
                .setUserId(param.getUserId())
                .setPrice(ques.getPrice())
                .setOrderState(orderStateEnums.getState())
                .setPayValidTime(LocalDateTime.now().plusHours(2))
                .setState(1)
                .setAddTime(LocalDateTime.now())
                .setAddUser(operatorUserId);

        if (orderStateEnums == QuestionOrderStateEnums.paid) {
            data.setPayTime(LocalDateTime.now());
        }

        if (orderMapper.insert(data) == 0) {
            return ResultEnums.Exception.getResult("数据写入失败");
        }

        Result<List<AddOrUpdQuesAnswerResult>> answerRes = answerService.addOrUpdQuesAnswer(new AddOrUpdQuesAnswerParam()
                        .setOrderId(data.getOrderId())
                        .setQuestionId(param.getQuestionId())
                        .setAnswerJsonStr(param.getAnswerJsonStr())
                , operator
        );

        if (answerRes.isErr()) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return answerRes.create();
        }

        List<AddOrUpdQuesAnswerResult> answerList = answerRes.getResult().stream()
                .filter(item -> !ListUtil.of(2, 5).contains(item.getRowType()) && StrUtil.isNotBlank(item.getValue()))
                .sorted(Comparator.comparingInt(AddOrUpdQuesAnswerResult::getRowMustFlag).reversed())
                .toList();

        if (answerList.size() > 3) {
            answerList = answerList.subList(0, 3);
        }

        ObjectMapper objectMapper = JacksonUtils.objectMapper();
        String cutStr = null;
        try {
            cutStr = objectMapper.writeValueAsString(answerList);
        } catch (JsonProcessingException ignored) {
        }

        //问答的节选，用于显示
        data.setAnswerCut(cutStr);
        orderMapper.updateById(data);

        return ResultEnums.Success.getDataResult(data.getOrderId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 300)
    public Result<Object> updQuesAnswer(@NonNull UpdQuesAnswerParam param, UserInfo operator) {
        String operatorUserId = operator != null ? operator.getUserId() : null;
        ObjectMapper objectMapper = JacksonUtils.objectMapper();

        //获取旧的订单
        XlQuestionOrder order = orderMapper.selectById(param.getOrderId());
        if (order == null || order.getState() != 1) {
            return ResultEnums.ParamError.getResult("未找到对应订单");
        }

        Result<List<AddOrUpdQuesAnswerResult>> answerRes = answerService.addOrUpdQuesAnswer(
                new AddOrUpdQuesAnswerParam()
                        .setOrderId(param.getOrderId())
                        .setQuestionId(order.getQuestionId())
                        .setAnswerJsonStr(param.getAnswerJsonStr())
                , operator
        );

        if (answerRes.isErr()) {
            return answerRes.create();
        }

        List<AddOrUpdQuesAnswerResult> answerList = answerRes.getResult().stream()
                .filter(item -> !ListUtil.of(2, 5).contains(item.getRowType()) && StrUtil.isNotBlank(item.getValue()))
                .sorted(Comparator.comparingInt(AddOrUpdQuesAnswerResult::getRowMustFlag).reversed())
                .toList();

        if (answerList.size() > 3) {
            answerList = answerList.subList(0, 3);
        }

        String cutStr = null;
        try {
            cutStr = objectMapper.writeValueAsString(answerList);
        } catch (JsonProcessingException ignored) {
        }

        //问答的节选，用于显示
        orderMapper.updateById(new XlQuestionOrder()
                .setAnswerCut(cutStr)
                .setUpdTime(LocalDateTime.now())
                .setUpdUser(operatorUserId)
        );

        return ResultEnums.Success.getResult();
    }

    @Override
    public Result<Object> updQuesOrderState(@NonNull UpdQuesOrderStateParam param, UserInfo operator) {
        String operatorUserId = operator != null ? operator.getUserId() : null;

        //获取旧的订单
        XlQuestionOrder order = orderMapper.selectById(param.getOrderId());
        if (order == null || order.getState() != 1) {
            return ResultEnums.ParamError.getResult("未找到对应订单");
        }
        QuestionOrderStateEnums oriStateEnums = QuestionOrderStateEnums.getByState(order.getOrderState());

        //改状态的无法更新其它内容
        QuestionOrderStateEnums stateEnums = QuestionOrderStateEnums.getByState(param.getOrderState());
        if (stateEnums == null) {
            return ResultEnums.ParamError.getResult("不支持的订单状态");
        }
        if (stateEnums == oriStateEnums) {
            return ResultEnums.Success.getResult();
        }


        XlQuestionOrder data = new XlQuestionOrder()
                .setOrderId(param.getOrderId())
                .setOrderState(param.getOrderState())
                .setUpdTime(LocalDateTime.now())
                .setUpdUser(operatorUserId);

        if (stateEnums == QuestionOrderStateEnums.cancel) {
            if (StrUtil.isBlank(param.getRemark())) {
                return ResultEnums.ParamError.getResult("取消备注不能为空");
            }
            data.setCancelRemark(param.getRemark())
                    .setCancelTime(LocalDateTime.now());
        } else if (stateEnums == QuestionOrderStateEnums.paid) {
            if (oriStateEnums != QuestionOrderStateEnums.add) {
                return ResultEnums.ParamError.getResult("该订单无法支付");
            }

            data.setPayTime(LocalDateTime.now());
        } else if (stateEnums == QuestionOrderStateEnums.add) {
            return ResultEnums.ParamError.getResult("无法设置订单为待支付状态");
        }

        if (orderMapper.updateById(data) == 0) {
            return ResultEnums.Exception.getResult("状态写入失败");
        }

        return ResultEnums.Success.getResult();
    }

    @Override
    public Result<QuesOrderDetailsResult> getQuesOrderDetails(@NonNull String orderId) {
        QueryQuesOrderParam param = new QueryQuesOrderParam()
                .setOrderId(orderId)
                .setAnswerDetailFlag(1)
                .setQuestionDetailFlag(1);
        Result<List<QuesOrderDetailsResult>> listRes = queryQuesOrderList(param);
        if (listRes.isErr()) {
            return listRes.create();
        }

        List<QuesOrderDetailsResult> list = listRes.getResult();
        if (list == null || list.isEmpty()) {
            return ResultEnums.BusinessError.getResult("未找到对应订单");
        }

        return ResultEnums.Success.getDataResult(list.get(0));
    }

    @Override
    public Result<List<QuesOrderDetailsResult>> queryQuesOrderList(@NonNull QueryQuesOrderParam param) {
        List<XlQuestionOrder> orderList = orderMapper.selectList(getQueryQuesOrderWrapper(param));
        return ResultEnums.Success.getListResult(
                orderDetailConverter(orderList, param.getAnswerDetailFlag(), param.getQuestionDetailFlag())
        );
    }

    @Override
    public Result<List<QuesOrderDetailsResult>> queryQuesOrderPage(@NonNull QueryQuesOrderParam param, SPage sPage) {
        Page<XlQuestionOrder> page = orderMapper.selectPage(SPage.getPage(sPage), getQueryQuesOrderWrapper(param));
        return ResultEnums.Success.getPageResult(
                orderDetailConverter(page.getRecords(), param.getAnswerDetailFlag(), param.getQuestionDetailFlag())
                , page.getTotal()
        );
    }

    private Wrapper<XlQuestionOrder> getQueryQuesOrderWrapper(@NonNull QueryQuesOrderParam param) {
        LambdaQueryWrapper<XlQuestionOrder> wrapper = new LambdaQueryWrapper<XlQuestionOrder>()
                .eq(XlQuestionOrder::getState, 1)
                .eq(StrUtil.isNotBlank(param.getOrderId()), XlQuestionOrder::getOrderId, param.getOrderId())
                .eq(StrUtil.isNotBlank(param.getUserId()), XlQuestionOrder::getUserId, param.getUserId())
                .eq(param.getQuestionId() != null, XlQuestionOrder::getQuestionId, param.getQuestionId())
                .ge(param.getAddBeginTime() != null, XlQuestionOrder::getAddTime, param.getAddBeginTime())
                .le(param.getAddEndTime() != null, XlQuestionOrder::getAddTime, param.getAddEndTime())
                .like(StrUtil.isNotBlank(param.getQuestionTitleLike()), XlQuestionOrder::getQuestionTitle, param.getQuestionTitleLike())
                .orderByDesc(XlQuestionOrder::getAddTime);

        if (StrUtil.isNotBlank(param.getOrderStates())) {
            wrapper.in(XlQuestionOrder::getOrderState, ListUtil.of(param.getOrderStates().split(",")));
        }

        return wrapper;
    }

    private List<QuesOrderDetailsResult> orderDetailConverter(
            List<XlQuestionOrder> orderList
            , Integer answerDetailFlag
            , Integer questionDetailFlag
    ) {
        if (orderList == null || orderList.isEmpty()) {
            return new ArrayList<>();
        }

        return orderList
                .stream()
                .map(item -> {
                    QuesOrderDetailsResult data = BeanUtil.copyProperties(item, QuesOrderDetailsResult.class);

                    //取出回答明细
                    if (answerDetailFlag != null && answerDetailFlag.equals(1)) {
                        Result<List<XlQuestionAnswer>> answerResult = answerService.queryQuesAnswer(data.getOrderId());
                        if (answerResult.isSuc()) {
                            data.setAnswer(answerResult.getResult());
                        }
                    }

                    //取出问题明细
                    if (questionDetailFlag != null && questionDetailFlag.equals(1)) {
                        Result<QuestionDetailsResult> quesDetailsRes = questionService.getQuestionDetails(data.getQuestionId());
                        if (quesDetailsRes.isSuc()) {
                            data.setQuestion(quesDetailsRes.getResult());
                        }
                    }
                    return data;
                }).toList();

    }
}
